package cn.lingyangwl.agile.pay.common.service.impl;

import cn.lingyangwl.agile.pay.common.assembly.MchAppAssembly;
import cn.lingyangwl.agile.pay.common.constants.Cs;
import cn.lingyangwl.framework.core.page.PageModel;
import cn.lingyangwl.framework.core.page.TableSupport;
import cn.lingyangwl.framework.mybatis.plus.utils.PageUtil;
import cn.lingyangwl.framework.tool.core.StringUtils;
import cn.lingyangwl.framework.tool.core.exception.BizException;
import cn.lingyangwl.agile.common.core.exception.enums.GlobalErrorEnum;
import cn.lingyangwl.agile.model.module.auth.LoginUser;
import cn.lingyangwl.agile.common.security.utils.SecurityUtils;
import cn.lingyangwl.agile.pay.model.entity.MchApp;
import cn.lingyangwl.agile.pay.model.entity.MchPayPassage;
import cn.lingyangwl.agile.pay.model.entity.PayInterfaceConfig;
import cn.lingyangwl.agile.pay.model.entity.PayOrder;
import cn.lingyangwl.agile.pay.model.rqrs.MchAppQL;
import cn.lingyangwl.agile.pay.model.rqrs.MchAppSaveRQ;
import cn.lingyangwl.agile.pay.model.rqrs.MchAppUpdateRQ;
import cn.lingyangwl.agile.pay.common.manager.MchInfoManager;
import cn.lingyangwl.agile.pay.common.manager.MchPayPassageManager;
import cn.lingyangwl.agile.pay.common.manager.PayInterfaceConfigManager;
import cn.lingyangwl.agile.pay.common.manager.PayMqSender;
import cn.lingyangwl.agile.pay.common.mapper.MchAppMapper;
import cn.lingyangwl.agile.pay.common.model.mq.ResetIsvMchAppInfoConfigMQ;
import cn.lingyangwl.agile.pay.common.service.MchAppService;
import cn.lingyangwl.agile.pay.common.service.PayOrderService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 商户应用表 服务实现类
 * </p>
 *
 * @author shenguangyang
 */
@Service
@RequiredArgsConstructor
public class MchAppServiceImpl extends ServiceImpl<MchAppMapper, MchApp> implements MchAppService {
    private final PayOrderService payOrderService;
    private final MchAppAssembly mchAppAssembly;
    private final MchPayPassageManager mchPayPassageManager;
    private final PayInterfaceConfigManager payInterfaceConfigManager;
    private final MchInfoManager mchInfoManager;
    private final PayMqSender payMqSender;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteByAppId(String appId) {
        MchApp mchApp = this.getById(appId);
        if (Objects.isNull(mchApp)) {
            throw new BizException("应用不存在");
        }

        // 1. 查看当前应用是否存在交易数据
        long payCount = payOrderService.count(PayOrder.lqw().eq(PayOrder::getAppId, appId));
        if (payCount > 0) {
            throw new BizException("该应用已存在交易数据，不可删除");
        }

        // 2. 删除应用关联的支付通道
        mchPayPassageManager.remove(MchPayPassage.lqw().eq(MchPayPassage::getAppId, appId));

        // 3.删除应用配置的支付参数
        payInterfaceConfigManager.remove(PayInterfaceConfig.lqw()
                .eq(PayInterfaceConfig::getInfoId, appId)
                .eq(PayInterfaceConfig::getInfoType, Cs.INFO_TYPE_MCH_APP)
        );

        // 4.删除当前应用
        if (!removeById(appId)) {
            throw new BizException(GlobalErrorEnum.OPERATION_FAIL_DELETE);
        }

        // 推送修改消息
        ResetIsvMchAppInfoConfigMQ mq = ResetIsvMchAppInfoConfigMQ
                .build(ResetIsvMchAppInfoConfigMQ.RESET_TYPE_MCH_APP, null, mchApp.getMchNo(), appId);
        payMqSender.send(mq);
    }

    @Override
    public MchApp getMchAppById(String appId) {
        return this.getById(appId);
    }

    @Override
    public IPage<MchApp> pageMchApp(MchAppQL query) {
        PageModel pageModel = TableSupport.getPageModel();

        LoginUser loginUser = SecurityUtils.getLoginUser();
        String mchNo = query.getMchNo();
        LambdaQueryWrapper<MchApp> wrapper = MchApp.lqw()
                .eq(StringUtils.isNotEmpty(mchNo), MchApp::getMchNo, mchNo)
                .eq(StringUtils.isNotEmpty(query.getAppId()), MchApp::getId, query.getAppId())
                .eq(StringUtils.isNotEmpty(query.getAppName()), MchApp::getAppName, query.getAppName())
                .eq(StringUtils.isNotEmpty(query.getStatus()), MchApp::getStatus, query.getStatus())
                .orderByDesc(MchApp::getCreatedAt);
        return this.page(PageUtil.to(pageModel), wrapper);
    }

    @Override
    public MchApp getByMch(String mchNo, String appId) {
        return getOne(MchApp.lqw().eq(MchApp::getMchNo, mchNo).eq(MchApp::getId, appId));
    }

    @Override
    public void saveMchApp(MchAppSaveRQ req) {
        mchInfoManager.checkExist(req.getMchNo());
        MchApp mchApp = mchAppAssembly.toMchApp(req);

        if (!this.save(mchApp)) {
            throw new BizException(GlobalErrorEnum.OPERATION_FAIL_CREATE);
        }
    }

    @Override
    public void updateMchApp(MchAppUpdateRQ req) {
        MchApp record = this.getById(req.getId());
        if (Objects.isNull(record)) {
            return;
        }

        MchApp mchApp = mchAppAssembly.toMchApp(req);
        if (!this.updateById(mchApp)) {
            throw new BizException(GlobalErrorEnum.OPERATION_FAIL_UPDATE);
        }

        // 推送修改消息
        ResetIsvMchAppInfoConfigMQ mq = ResetIsvMchAppInfoConfigMQ
                .build(ResetIsvMchAppInfoConfigMQ.RESET_TYPE_MCH_APP, null, record.getMchNo(), record.getId());
        payMqSender.send(mq);
    }

    @Override
    public List<MchApp> listAllMchApp() {
        return list(MchApp.lqw());
    }
}
